/*
 *  Copyright 2019-2020 Zheng Jie
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package me.zhengjie.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.RequiredArgsConstructor;
import me.zhengjie.domain.KwExamStudent;
import me.zhengjie.exception.ParameterException;
import me.zhengjie.mapper.ExamRoomMapper;
import me.zhengjie.pojo.entity.ExamRoom;
import me.zhengjie.repository.KwExamStudentRepository;
import me.zhengjie.service.KwExamStudentService;
import me.zhengjie.service.dto.KwExamStudentDto;
import me.zhengjie.service.dto.KwExamStudentQueryCriteria;
import me.zhengjie.service.mapstruct.KwExamStudentMapper;
import me.zhengjie.util.AssertUtils;
import me.zhengjie.util.KwUtils;
import me.zhengjie.utils.*;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author LongYang
 * @website https://el-admin.vip
 * @description 服务实现
 * @date 2021-06-28
 **/
@Service
@RequiredArgsConstructor
public class KwExamStudentServiceImpl implements KwExamStudentService {

    private final KwExamStudentRepository kwExamStudentRepository;
    private final KwExamStudentMapper kwExamStudentMapper;

    private final ExamRoomMapper examRoomMapper;
    private final KwUtils kwUtils;

    @Override
    public Map<String, Object> queryAll(KwExamStudentQueryCriteria criteria, Pageable pageable) {
        if (criteria.getExamId() == null) return null;
        Page<KwExamStudent> page = kwExamStudentRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder), pageable);
        return PageUtil.toPage(page.map(kwExamStudentMapper::toDto));
    }

    @Override
    public List<KwExamStudentDto> queryAll(KwExamStudentQueryCriteria criteria) {
        if (criteria.getExamId() == null) return null;
        return kwExamStudentMapper.toDto(kwExamStudentRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder)));
    }

    @Override
    @Transactional
    public KwExamStudentDto findById(Integer id) {
        KwExamStudent kwExamStudent = kwExamStudentRepository.findById(id).orElseGet(KwExamStudent::new);
        ValidationUtil.isNull(kwExamStudent.getId(), "KwExamStudent", "id", id);
        return kwExamStudentMapper.toDto(kwExamStudent);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseEntity<Object> create(KwExamStudent resources) {

        if (resources.getExamId() != null && StringUtils.isNotBlank(resources.getExaminee())) {
            List<KwExamStudent> list = kwExamStudentRepository.findByExamIdAndExamInee(resources.getExamId(), resources.getExaminee());
            if (!list.isEmpty()) throw new ParameterException("该场考试下不允许出现重复准考证");

        }
        List<KwExamStudent> list = kwExamStudentRepository.findByExamIdAndExamRoomId(resources.getExamId(), resources.getExamRoomId());
        if (!list.isEmpty()) {
            list.forEach(s -> {
                AssertUtils.isNotEq(s.getIdCard(), resources.getIdCard(), "已存在该考生的本次考试信息");
                if (!Objects.equals(s.getId(), resources.getId()) && Objects.equals(s.getSeat(), resources.getSeat())) {
                    throw new ParameterException("该考场的座位号已经有其他同学入座了");
                }
            });
        }
        /*校验该考场是否还能容纳考生*/
        if (resources.getExamRoomId() != null) {
            QueryWrapper<ExamRoom> wrapper = new QueryWrapper<>();
            wrapper.eq("id", resources.getExamRoomId())
                    .eq("exam_id", resources.getExamId());
            ExamRoom examRoom = examRoomMapper.selectOne(wrapper);
            if (examRoom != null && examRoom.getSeatNumber() <= list.size())
                throw new ParameterException(examRoom.getNameCn() + "考场只能容纳" + examRoom.getSeatNumber() + "人");
        }


        return new ResponseEntity<>(kwExamStudentMapper.toDto(kwExamStudentRepository.save(resources)), HttpStatus.CREATED);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(KwExamStudent resources) {
        /*如果是成绩复核或者成绩证明则不判断座位号是否重复*/
        if (StringUtils.isNotBlank(resources.getScoreStatus()) ||
                StringUtils.isNotBlank(resources.getScoreReviewBack()) ||
                StringUtils.isNotBlank(resources.getScoreReviewReson()) ||
                StringUtils.isNotBlank(resources.getStatus()) ||
                StringUtils.isNotBlank(resources.getStatusProveReason())) {
            KwExamStudent kwExamStudent = new KwExamStudent();
            BeanUtils.copyProperties(resources, kwExamStudent);
            kwExamStudentRepository.save(kwExamStudent);
            return;
        }
        KwExamStudent kwExamStudent = kwExamStudentRepository.findById(resources.getId()).orElseGet(KwExamStudent::new);
        ValidationUtil.isNull(kwExamStudent.getId(), "KwExamStudent", "id", resources.getId());
        List<KwExamStudent> list = kwExamStudentRepository.findByExamIdAndExamRoomId(resources.getExamId(), resources.getExamRoomId());
        if (!list.isEmpty()) {
            list.forEach(s -> {
                if (!Objects.equals(s.getId(), resources.getId()) && Objects.equals(s.getSeat(), resources.getSeat())) {
                    throw new ParameterException("该考场的座位号已经有其他同学入座了");
                }
            });
        }
        List<KwExamStudent> students = kwExamStudentRepository.findByExamIdAndExamInee(resources.getExamId(), resources.getExaminee());
        if (!students.isEmpty()) {
            students.forEach(s -> {
                if (!Objects.equals(s.getId(), resources.getId()) && Objects.equals(s.getExaminee(), resources.getExaminee())) {
                    throw new ParameterException("该场考试下不允许出现重复准考证");
                }
            });
        }

        kwExamStudent.copy(resources);
        kwExamStudentRepository.save(kwExamStudent);
    }

    @Override
    public void deleteAll(Integer[] ids) {
        List<KwExamStudent> examStudents = kwExamStudentRepository.findAllById(Arrays.asList(ids));
        List<Integer> examIds = examStudents.stream().map(KwExamStudent::getExamId).collect(Collectors.toList());
        boolean permission = kwUtils.hasOtherPermission(examIds);
        if (!permission) {
            throw new ParameterException("无权操作");
        }
        for (Integer id : ids) {
            kwExamStudentRepository.deleteById(id);
        }
    }

    @Override
    public void download(List<KwExamStudentDto> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (KwExamStudentDto kwExamStudent : all) {
            Map<String, Object> map = new LinkedHashMap<>();
            map.put("考试id", kwExamStudent.getExamId());
            map.put("准考证号", kwExamStudent.getExaminee());
            map.put("考生id", kwExamStudent.getStudentId());
            map.put("身份证号", kwExamStudent.getIdCard());
            map.put("考生姓名", kwExamStudent.getNameCn());
            map.put("考场id", kwExamStudent.getExamRoomId());
            map.put("座位号", kwExamStudent.getSeat());
            map.put("成绩", kwExamStudent.getScore());
            map.put("成绩复核状态（0：未申请，1：已申请，2：通过，3：拒绝，4：已复核）", kwExamStudent.getScoreStatus());
            map.put("成绩复核回复说明", kwExamStudent.getScoreReviewBack());
            map.put("成绩复核申请理由", kwExamStudent.getScoreReviewReson());
            map.put("成绩证明状态（0：未申请，1：已申请，2：通过，3：拒绝，4：已处理）", kwExamStudent.getStatus());
            map.put("删除标识（0：未删除，2：已删除）", kwExamStudent.getDelFlag());
            map.put("考生手机号", kwExamStudent.getPhone());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }
}